package com.appleframework.core.io;

import java.util.Arrays;

/**
 * see http://www.w3.org/TR/REC-xml/#sec-guessing-no-ext-info
 * 
 * @author Santhosh Kumar T
 */
public enum BOM {
   UTF8(
            IOUtility.UTF_8.name(),
            new int[] { 0xEF, 0xBB, 0xBF },
            null),
   UCS4_LE(
            "UCS-4LE",
            new int[] { 0xFF, 0xFE, 0x00, 0x00 },
            new int[] { 0x3C, 0x00, 0x00, 0x00 }),
   UCS4_BE(
            "UCS-4BE",
            new int[] { 0x00, 0x00, 0xFE, 0xFF },
            new int[] { 0x00, 0x00, 0x00, 0x3C }),
   UCS4_2143(
            "UCS-4-2143",
            new int[] { 0x00, 0x00, 0xFF, 0xFE },
            new int[] { 0x00, 0x00, 0x3C, 0x00 }),
   UCS4_3412(
            "UCS-4-3412",
            new int[] { 0xFE, 0xFF, 0x00, 0x00 },
            new int[] { 0x00, 0x3C, 0x00, 0x00 }),
   UTF16_LE(
            IOUtility.UTF_16LE.name(),
            new int[] { 0xFF, 0xFE },
            new int[] { 0x3C, 0x00, 0x3F, 0x00 }),
   UTF16_BE(
            IOUtility.UTF_16BE.name(),
            new int[] { 0xFE, 0xFF },
            new int[] { 0x00, 0x3C, 0x00, 0x3F }),
   ASCII(
            IOUtility.UTF_8.name(),
            null,
            new int[] { 0x3C, 0x3F, 0x78, 0x6D }),
   EBCDIC(
            "Cp037",
            null,
            new int[] { 0x4C, 0x6F, 0xA7, 0x94 }), ;

   private String encoding;
   private byte with[];
   private byte without[];

   BOM(String encoding, int[] with, int[] without) {
      this.encoding = encoding;
      this.with = toBytes(with);
      this.without = toBytes(without);
   }

   private static byte[] toBytes(int[] arr) {
      if (arr == null) {
         return null;
      } else {
         byte b[] = new byte[arr.length];
         for (int i = 0; i < arr.length; i++) {
            b[i] = (byte) arr[i];
         }
         return b;
      }
   }

   public String encoding() {
      return encoding;
   }

   public byte[] with() {
      return with == null ? new byte[0] : Arrays.copyOf(with, with.length);
   }

   public byte[] without() {
      return without == null ? new byte[0] : Arrays.copyOf(without, without.length);
   }

   public static BOM get(byte b[], boolean with) {
      for (BOM bom : values()) {
         byte expected[] = with ? bom.with() : bom.without();
         if (expected != null && b.length >= expected.length) {
            boolean matched = true;
            for (int i = 0; i < expected.length; i++) {
               if (expected[i] != b[i]) {
                  matched = false;
                  break;
               }
            }
            if (matched) {
               return bom;
            }
         }
      }
      return null;
   }
}
